﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Http;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Extentions;
using TrainingReminderSystem.Model;
using TrainingReminderSystem.Dal;
using System.Threading.Tasks;

namespace TrainingReminderSystem.Bll
{
    /// <summary>
    /// 客户信息 逻辑层
    /// </summary>
    public partial class SysCustomerBll
    {
        #region 添加和编辑的时候 验证数据和设置默认值

        /// <summary>
        /// 添加和编辑的时候 验证数据和设置默认值
        /// </summary>
        /// <param name="model"></param>
        /// <param name="isAdd">添加还是编辑,可以不管此参数</param>/// <param name="db"></param>
        /// <returns>是否通过,true表示验证通过,false代表验证没有通过</returns>
        public AjaxResult<dynamic> Validate(SysCustomer model, bool isAdd, DbEntities db)
        {
            var r = new AjaxResult<dynamic>();
            if (model == null)
            {
                r.Message = LanguageHelper.NoSubmitData;
                return r;
            }
            model.ExTrimProperty();

            model.HeaderUrl = Base64Helper.SaveFileFromBase64(model.HeaderUrl);
            model.PY = ToolHelper.GetPy(model.SysCustomerName);
            if (string.IsNullOrEmpty(model.Phone))
            {
                r.Message = LanguageHelper.RequireString1<SysCustomer>(nameof(SysCustomer.Phone));
                return r;
            }

            //if (model.SysStoreID <= 0)
            //{
            //    r.Message = LanguageHelper.RequireString2<SysCustomer>(nameof(SysCustomer.SysStoreID));
            //    return r;
            //}
            //修改的时候,不会更改此字段
            if (SysConfig.EnumRunProject == EnumRunProject.系统后台端)
            {
                model.CreateSysEmployeeID = PcLoginedBll.CurrentEmployee?.SysEmployeeID;
                model.SysStoreID = PcLoginedBll.CurrentStore?.SysStoreID ?? 0;
            }
            else if (SysConfig.EnumRunProject == EnumRunProject.微信客户端)
            {
                model.SysStoreID = CustomerLoginedBll.CurrentStore?.SysStoreID ?? 0;
            }

            if (isAdd)
            {
                model.EnumStatus = EnumStatus.启用;
                model.CreateDate = DateTime.Now;
            }
            r = ValidatePartial(model, isAdd, r, db);
            if (r.Success == false) return r;
            r.Success = true;
            return r;
        }

        #endregion

        #region 分页方法

        /// <summary>
        /// 查询条件,能替换掉一些属性查询为自定义查询
        /// </summary>
        /// <param name="where"></param>
        /// <param name="key"></param>
        /// <param name="val"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        private Expression<Func<SysCustomer, bool>> InitSearchDelegete(Expression<Func<SysCustomer, bool>> where, string key, string val, DbEntities db)
        {
            var r = InitSearchDelegetePartial(where, key, val, db);
            if (r != null) return r;
            return null;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="index"></param>
        /// <param name="size"></param>
        /// <param name="form"></param>
        /// <param name="sortField"></param>
        /// <param name="asc"></param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> GetListByPage(int index, int size, IFormCollection form = null, string sortField = "", bool asc = false)
        {
            using (var db = PcLoginedBll.Db)
            {
                Expression<Func<SysCustomer, bool>> where = InitSearch<SysCustomer, DbEntities>(form, InitSearchDelegete, db); //拼接查询条件方法
                IQueryable<SysCustomer> query = OrderByPartial(db.SysCustomer, sortField, asc, db);
                int counts;
                var tempIDList = query.ExGetListByPage(index, size, out counts, where).Select(m => m.SysCustomerID);
                var r = new AjaxResult<dynamic>();
                r.Total = counts;
                IQueryable<SysCustomer> list = query.Where(m => tempIDList.Contains(m.SysCustomerID));
                var tempList = list.Select(m => new
                {
                    SysCustomerID = m.SysCustomerID,
                    EnumSysCustomerType = m.EnumSysCustomerType,
                    HeaderUrl = m.HeaderUrl,
                    SysCustomerName = m.SysCustomerName,
                    PY = m.PY,
                    Phone = DbFun.fn_replaceNum(m.Phone, CanSeePhone),
                    BirthDay = m.BirthDay,
                    EnumStatus = m.EnumStatus,
                    CreateDate = m.CreateDate,
                    Remark = m.Remark,

                    m.SysStoreID,
                    m.IsDemo,

                    SysStore = new { m.SysStore.SysStoreName, m.SysStore.EnumStatus, m.SysStore.EnumSysStoreType },

                    WechatH5 = m.SysCustomerOpenID.Where(n => n.EnumOpenIDType == EnumOpenIDType.微信公众号).Select(n => n.OpenID).ToList(),
                    WechatMini = m.SysCustomerOpenID.Where(n => n.EnumOpenIDType == EnumOpenIDType.微信小程序).Select(n => n.OpenID).ToList(),

                    m.CreateSysEmployeeID,
                    CreateSysEmployee = db.SysEmployee.Select(n => new
                    {
                        n.SysEmployeeName
                    }).FirstOrDefault(),

                    SysEmployee = new { m.SysEmployee.SysEmployeeName },

                    m.EnumSysCustomerSource,
                    m.EnumSysCustomerIntention,

                    //SysCustomerOpenID = m.SysCustomerOpenID.Take(1).FirstOrDefault()
                    //SysCustomerOpenID = m.SysCustomerOpenID.FirstOrDefault()//sql生成有问题,会自己给加个排序,加个Take(1)

                    CertSearch03Json = m.CertSearch03Json,
                    CertSearch02Json = m.CertSearch02Json,
                    CertSearchUpdateTime = m.CertSearchUpdateTime,
                    ReferrerID = m.ReferrerID,
                    Referrer = new ReferrerExPart()
                    {
                        ReferrerID = m.Referrer.ReferrerID,
                        Name = m.Referrer.Name,
                        Phone = DbFun.fn_replaceNum(m.Referrer.Phone, CanSeePhone),
                        EnumStatus = m.Referrer.EnumStatus
                    },
                    EnumGender = m.EnumGender,
                    Address = m.Address,
                    Company = m.Company,
                    Qualification = m.Qualification,

                    SysCustomerIdCard = m.SysCustomerIdCard.ToList()
                });
                var resultList = await tempList.ToListAsync();
                //return GetListByPagePartial(resultList, r, db);

                r.Success = true;
                r.Result = resultList;
                return r;
            }
        }

        #endregion

        #region 得到单对象,返回值有可能为null

        /// <summary>
        /// 得到单对象,返回值有可能为null
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        public async Task<AjaxResult<SysCustomer>> GetModel(int id)
        {
            using (var db = PcLoginedBll.Db)
            {
                return await GetModel(id, db);
            }
        }

        internal async Task<AjaxResult<SysCustomer>> GetModel(int id, DbEntities db)
        {
            string include = GetModelIncludePartial();
            IQueryable<SysCustomer> query = !string.IsNullOrWhiteSpace(include) ? db.SysCustomer.Include(include) : db.SysCustomer;
            var temp = query.Where(m => m.SysCustomerID == id);
            var dbModel = await temp.FirstOrDefaultAsync();
            return GetModelReturnPartial(dbModel, db);
        }

        #endregion

        #region 保存数据

        /// <summary>
        /// 保存数据
        /// </summary>
        /// <param name="model">保存的对象,成功之后model对象的model对象的主键能得到对象</param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> Save(SysCustomer model)
        {
            using (var db = PcLoginedBll.Db)
            {
                if (model.SysCustomerID <= 0)
                {
                    return await Add(model, db);
                }
                return await Update(model, db);
            }
        }

        #endregion

        #region 添加数据

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> Add(SysCustomer model)
        {
            using (var db = PcLoginedBll.Db)
            {
                return await Add(model, db);
            }
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal async Task<AjaxResult<dynamic>> Add(SysCustomer model, DbEntities db)
        {
            var r = new AjaxResult<dynamic>() { Success = false };
            if (db == null) db = PcLoginedBll.Db;
            var tempAr = Validate(model, true, db);
            if (tempAr.Success == false)
            {
                r.Message = tempAr.Message;
                r.Result = tempAr.Result;
                r.Total = tempAr.Total;
                return r;
            }
            var tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = await db.Database.BeginTransactionAsync();
            try
            {
                db.SysCustomer.Add(model);
                string error = AddLog(db, model, EnumLogType.新建);
                if (!string.IsNullOrEmpty(error))
                {
                    return AjaxResult<dynamic>.ErrorResult(error);
                }
                await db.SaveChangesAsync();
                r = AddUpdateSuccessPartial(model, true, r, db);
                if (r.Success == false)
                {
                    return r;
                }
                await db.SaveChangesAsync();
                if (hasTran == false)
                {
                    await tran.CommitAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
                r.Success = true;
                r.Message = LanguageHelper.Success;
                r.Result = model;
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError(GetCurrentOther());
                r.Total = (int)EnumTotal.异常;
                r.Success = false;
                r.Message = string.Format(LanguageHelper.Fail1, ex.ExMessageWithInner());
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null)
                {
                    await tran.RollbackAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
            }
        }

        #endregion

        #region 编辑Old

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> Update(SysCustomer model)
        {
            using (var db = PcLoginedBll.Db)
            {
                return await Update(model, db);
            }
        }

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal async Task<AjaxResult<dynamic>> Update(SysCustomer model, DbEntities db)
        {
            var r = new AjaxResult<dynamic>() { Success = false };
            if (db == null) db = PcLoginedBll.Db;
            var tempAr = Validate(model, false, db);
            if (tempAr.Success == false)
            {
                r.Message = tempAr.Message;
                r.Result = tempAr.Result;
                r.Total = tempAr.Total;
                return r;
            }
            var tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = await db.Database.BeginTransactionAsync();
            try
            {
                var dbModel = await db.SysCustomer.Include(m => m.SysCustomerIdCard).Include(m => m.SysCustomerOrganizationTrain).FirstOrDefaultAsync(m => m.SysCustomerID == model.SysCustomerID);
                if (dbModel == null)
                {
                    r.Message = LanguageHelper.NoData;
                    return r;
                }
                if (model.SysCustomerName != dbModel.SysCustomerName || model.SysCustomerIdCard.FirstOrDefault()?.IdCard != dbModel.SysCustomerIdCard.FirstOrDefault()?.IdCard)
                {
                    model.CertSearchUpdateTime = null;
                }

                dbModel.EnumSysCustomerType = model.EnumSysCustomerType;
                dbModel.HeaderUrl = model.HeaderUrl;
                dbModel.SysCustomerName = model.SysCustomerName;
                dbModel.Phone = model.Phone;
                dbModel.BirthDay = model.BirthDay;
                dbModel.EnumStatus = model.EnumStatus;
                dbModel.Remark = model.Remark;
                dbModel.PY = model.PY;

                dbModel.SysEmployeeID = model.SysEmployeeID;
                dbModel.EnumSysCustomerSource = model.EnumSysCustomerSource;
                dbModel.EnumSysCustomerType = model.EnumSysCustomerType;

                //dbModel.CreateSysEmployeeID = model.CreateSysEmployeeID;
                //dbModel.CreateDate = model.CreateDate;
                dbModel.EnumSysCustomerIntention = model.EnumSysCustomerIntention;
                dbModel.CertSearch03Json = model.CertSearch03Json;
                dbModel.CertSearch02Json = model.CertSearch02Json;
                dbModel.CertSearchUpdateTime = model.CertSearchUpdateTime;
                dbModel.ReferrerID = model.ReferrerID;
                dbModel.EnumGender = model.EnumGender;
                dbModel.Address = model.Address;
                dbModel.Company = model.Company;
                dbModel.Qualification = model.Qualification;


                string error = AddLog(db, model, EnumLogType.编辑);
                if (!string.IsNullOrEmpty(error))
                {
                    return AjaxResult<dynamic>.ErrorResult(error);
                }
                await db.SaveChangesAsync();
                r = AddUpdateSuccessPartial(model, false, r, db, dbModel);
                if (r.Success == false)
                {
                    return r;
                }
                await db.SaveChangesAsync();
                if (hasTran == false)
                {
                    await tran.CommitAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }

                ClearCache(dbModel.SysCustomerID);

                r.Success = true;
                r.Message = LanguageHelper.Success;
                r.Result = dbModel;
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError(GetCurrentOther());
                r.Total = (int)EnumTotal.异常;
                r.Success = false;
                r.Message = string.Format(LanguageHelper.Fail1, ex.ExMessageWithInner());
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null)
                {
                    await tran.RollbackAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
            }
        }

        #endregion

        #region 删除

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> Del(int id)
        {
            using (var db = PcLoginedBll.Db)
            {
                return await Del(id, db);
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal async Task<AjaxResult<dynamic>> Del(int id, DbEntities db)
        {
            var r = new AjaxResult<dynamic>() { Success = false };
            if (db == null) db = PcLoginedBll.Db;
            var tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = await db.Database.BeginTransactionAsync();
            try
            {
                var dbModel = await db.SysCustomer.FirstOrDefaultAsync(m => m.SysCustomerID == id);
                if (dbModel == null)
                {
                    r.Message = LanguageHelper.NoData;
                    return r;
                }

                r = DelValidatePartial(dbModel, r, db);
                if (r.Success == false)
                {
                    return r;
                }
                //db.SysCustomer.Remove(dbModel);
                dbModel.IsDel = true;
                string error = AddLog(db, dbModel, EnumLogType.删除);
                if (!string.IsNullOrEmpty(error))
                {
                    return AjaxResult<dynamic>.ErrorResult(error);
                }
                await db.SaveChangesAsync();
                r = DelSuccessPartial(dbModel, r, db);
                if (r.Success == false)
                {
                    return r;
                }
                await db.SaveChangesAsync();
                if (hasTran == false)
                {
                    await tran.CommitAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
                r.Success = true;
                r.Message = LanguageHelper.Success;
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError(GetCurrentOther());
                r.Total = (int)EnumTotal.异常;
                r.Success = false;
                r.Message = string.Format(LanguageHelper.Fail1, ex.ExMessageWithInner());
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null)
                {
                    await tran.RollbackAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
            }
        }

        #endregion

        #region 下拉选择

        /// <summary>
        /// 下拉选择
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> GetListSelect(IFormCollection form = null)
        {
            using (var db = PcLoginedBll.Db)
            {
                Expression<Func<SysCustomer, bool>> where = InitSearch<SysCustomer, DbEntities>(form, InitSearchDelegete, db); //拼接查询条件方法
                var selectID = form["selectIDName"].ExTrim();
                var obj = db.SysCustomer.AsNoTracking();
                bool hasSelectID = false;
                if (!string.IsNullOrEmpty(selectID))
                {
                    if (selectID.IndexOf(',') != -1)
                    {
                        var selectIDList = selectID.ExToSplitList(',', false);
                        if (selectIDList.Count > 0)
                        {
                            hasSelectID = true;
                            obj = obj.OrderByDescending(m => selectIDList.Contains(m.SysCustomerID)).ThenByDescending(m => m.SysCustomerID);
                        }
                    }
                    else
                    {
                        var selectIDInt = selectID.ExToInt32();
                        if (selectIDInt > 0)
                        {
                            hasSelectID = true;
                            obj = obj.OrderByDescending(m => selectIDInt == m.SysCustomerID).ThenByDescending(m => m.SysCustomerID);
                        }
                    }
                    if (hasSelectID == false)
                    {
                        obj = obj.OrderByDescending(m => m.SysCustomerID);
                        where = where.ExAnd(m => m.SysCustomerName.Contains(selectID) || m.PY.Contains(selectID));
                    }
                }
                if (hasSelectID == false)
                {
                    obj = obj.OrderByDescending(m => m.SysCustomerID);
                    where = where.ExAnd(m => m.EnumStatus == EnumStatus.启用);
                }
                var result = new AjaxResult<dynamic>() { Success = true };
                IQueryable<SysCustomer> list = obj.Where(where).Take(DefaultSize);
                var tempList = list.Select(m => new
                {
                    SysCustomerID = m.SysCustomerID,
                    EnumSysCustomerType = m.EnumSysCustomerType,
                    HeaderUrl = m.HeaderUrl,
                    SysCustomerName = m.SysCustomerName,
                    PY = m.PY,
                    Phone = DbFun.fn_replaceNum(m.Phone, CanSeePhone),
                    BirthDay = m.BirthDay,
                    EnumStatus = m.EnumStatus,
                    CreateDate = m.CreateDate,
                    Remark = m.Remark,
                    m.SysStoreID,
                    m.IsDemo,

                    SysStore = new { m.SysStore.SysStoreName, m.SysStore.EnumStatus, m.SysStore.EnumSysStoreType },

                    m.SysEmployeeID,
                    m.EnumSysCustomerSource,
                    m.EnumSysCustomerIntention,

                    //CertSearch03Json = m.CertSearch03Json,
                    //CertSearch02Json = m.CertSearch02Json,
                    //CertSearchUpdateTime = m.CertSearchUpdateTime,
                    ReferrerID = m.ReferrerID,
                    EnumGender = m.EnumGender,
                    Address = m.Address,
                    Company = m.Company,
                    Qualification = m.Qualification
                });
                result.Result = await tempList.ToListAsync();
                return result;
            }
        }

        #endregion

        #region 修改状态

        /// <summary>
        /// 修改状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> UpdateEnumStatus(int id, int status)
        {
            using (var db = PcLoginedBll.Db)
            {
                return await UpdateEnumStatus(id, status, db);
            }
        }

        /// <summary>
        /// 修改状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal async Task<AjaxResult<dynamic>> UpdateEnumStatus(int id, int status, DbEntities db)
        {
            var r = new AjaxResult<dynamic>() { Success = false };
            if (db == null) db = PcLoginedBll.Db;
            var tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = await db.Database.BeginTransactionAsync();
            try
            {
                var dbModel = await db.SysCustomer.FirstOrDefaultAsync(m => m.SysCustomerID == id);
                if (dbModel == null)
                {
                    r.Message = LanguageHelper.NoData;
                    return r;
                }

                r = UpdateEnumStatusValidatePartial(dbModel, r, db);
                if (r.Success == false)
                {
                    return r;
                }

                dbModel.EnumStatus = (EnumStatus)status;
                string error = AddLog(db, new SysCustomer() { SysCustomerID = id, EnumStatus = dbModel.EnumStatus }, EnumLogType.修改状态);
                if (!string.IsNullOrEmpty(error))
                {
                    return AjaxResult<dynamic>.ErrorResult(error);
                }
                await db.SaveChangesAsync();
                r = UpdateEnumStatusSuccessPartial(dbModel, r, db);
                if (r.Success == false)
                {
                    return r;
                }
                await db.SaveChangesAsync();
                if (hasTran == false)
                {
                    await tran.CommitAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
                r.Success = true;
                r.Message = LanguageHelper.Success;
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError(GetCurrentOther());
                r.Total = (int)EnumTotal.异常;
                r.Success = false;
                r.Message = string.Format(LanguageHelper.Fail1, ex.ExMessageWithInner());
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null)
                {
                    await tran.RollbackAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
            }
        }

        #endregion

        //#region 导入
        //#endregion
    }
}
